#include "ftpclient.h"
#include "protocol.h"
#include <fcntl.h>
#include <sys/stat.h>
#include <dirent.h>
// #define DEBUG
#ifndef DT_DIR
#define DT_DIR 4
#endif
#ifndef DT_REG
#define DT_REG 8
#endif

int init_tcpclient(const char *ip, short port) {
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (-1 == sockfd) {
        perror("create socket failed");
        return -1;
    }
    struct sockaddr_in saddr;
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(port);
    saddr.sin_addr.s_addr = inet_addr(ip);
    if (-1 ==connect(sockfd, (struct sockaddr *)&saddr, sizeof(saddr))) {
        perror("connect failed");
        return -1;
    }
    return sockfd;
}


void cmd_bye(int sockfd) {
    enum CMD_NO cmd_no = FTP_CMD_BYE;
    char cmd[1024] = {0};
    int i = 0;
    // 包头(1)	包长度(4)	 命令号(4)  包尾(1)
    cmd[i++] = 0xc0;
    int pkg_len = 4 + 4;
    cmd[i++] = 0xff & (pkg_len);
    cmd[i++] = 0xff & (pkg_len >> 8);
    cmd[i++] = 0xff & (pkg_len >> 16);
    cmd[i++] = 0xff & (pkg_len >> 24);
    // enum CMD_NO cmd_no = FTP_CMD_BYE;
    cmd[i++] = 0xff & (cmd_no);
    cmd[i++] = 0xff & (cmd_no >> 8);
    cmd[i++] = 0xff & (cmd_no >> 16);
    cmd[i++] = 0xff & (cmd_no >> 24);
    cmd[i++] = 0xc0;
    write(sockfd, cmd, i);
}

void cmd_ls(int sockfd) {
    // 包头(1)	包长度(4)	 命令号(4)  包尾(1)
    char cmd[1024] = {0};
    int i = 0;
    cmd[i++] = 0xc0;
    int pkg_len = 4 + 4;
    cmd[i++] = 0xff & (pkg_len);
    cmd[i++] = 0xff & (pkg_len >> 8);
    cmd[i++] = 0xff & (pkg_len >> 16);
    cmd[i++] = 0xff & (pkg_len >> 24);
    enum CMD_NO cmd_no = FTP_CMD_LS;
    cmd[i++] = 0xff & (cmd_no);
    cmd[i++] = 0xff & (cmd_no >> 8);
    cmd[i++] = 0xff & (cmd_no >> 16);
    cmd[i++] = 0xff & (cmd_no >> 24);
    cmd[i++] = 0xc0;
    write(sockfd, cmd, i);
}

void recv_ls_resp(int sockfd) {
    unsigned char cmd[8192] =  {0};
    int i = 0;
    int r;
    unsigned char ch;
    do {
        r = read(sockfd, &ch, 1);
        if (r <= 0) {
            perror("server dead!\n");
            break;
        }
    } while (ch != 0xc0);
    while (ch == 0xc0) {
        r = read(sockfd, &ch, 1);
        if (r <= 0) {
            perror("server dead!\n");
            break;
        }
    }
    while (ch != 0xc0) {
        cmd[i++] = ch;
        int r = read(sockfd, &ch, 1);
        if (r <= 0) {
            break;
        }
    }
    int pkg_len = cmd[0] | (cmd[1] << 8) | (cmd[2] << 16) | (cmd[3] << 24);
    if (i != pkg_len) {
#ifdef DEBUG
        printf("i = %d, pkg_len = %d\n", i, pkg_len);
#endif
        return;
    }
    int cmd_no = cmd[4] | (cmd[5] << 8) | (cmd[6] << 16) | (cmd[7] << 24);
    if (cmd[12] == 1) {
        printf("FTP_CMD_LS failed");
        int errnum = cmd[13] | (cmd[14] << 8) | (cmd[15] << 16) | (cmd[16] << 24);
        perror(strerror(errnum));
    } else {
        printf("%s", cmd + 13);
    }
}

void cmd_get(int sockfd, const char *str) {
    char file[256] = {0};
    strcpy(file, str);
    char *t = file;
    /*获取文件名，跳过空格*/
    while (*t == ' ') {
        t++;
    }
    if (strlen(t) == 0 || *t == '\n') {
        fputs("Usage: get filename\n", stderr);
        return;
    }
    char filename[256] = {0};
    // strncpy(filename, t, strlen(t));
    sscanf(t, "%s", filename);
    // filename[strlen(filename) - 1] = '\0';
    char cmd[1024] = {0};
    int i = 0;
    // 包头(1)	包长度(4)	 命令号(4)  参数长度(4)  参数内容(文件名长度)  包尾(1)
    cmd[i++] = 0xc0;
    int arg_len = strlen(filename);
    int pkg_len = 4 + 4 + 4 + arg_len;
    cmd[i++] = 0xff & (pkg_len);
    cmd[i++] = 0xff & (pkg_len >> 8);
    cmd[i++] = 0xff & (pkg_len >> 16);
    cmd[i++] = 0xff & (pkg_len >> 24);
    enum CMD_NO cmd_no = FTP_CMD_GET;
    cmd[i++] = 0xff & (cmd_no);
    cmd[i++] = 0xff & (cmd_no >> 8);
    cmd[i++] = 0xff & (cmd_no >> 16);
    cmd[i++] = 0xff & (cmd_no >> 24);

    cmd[i++] = 0xff & (arg_len);
    cmd[i++] = 0xff & (arg_len >> 8);
    cmd[i++] = 0xff & (arg_len >> 16);
    cmd[i++] = 0xff & (arg_len >> 24);

    memcpy(cmd + i, filename, arg_len);
    i += arg_len;
    cmd[i++] = 0xc0;
    write(sockfd, cmd, i);
    recv_get_resp(sockfd, filename);
}

void recv_get_resp(int sockfd, const char *filename) {
    #ifdef DEBUG
    printf("filename =%s\n", filename);
    #endif
    unsigned char buf[1024] = {0};
    int i = 0;
    unsigned char ch;
    /*解析服务器发送的数据包*/
    do {
        int r = read(sockfd, &ch, 1);
        if (r <= 0) {
            break;
        }
    } while (ch != 0xc0);
    while (ch == 0xc0) {
        #ifdef DEBUG
        #endif
        int r = read(sockfd, &ch, 1);
        if (r <= 0) {
            break;
        }
    }
    while (ch != 0xc0) {
        #ifdef DEBUG
        #endif
        buf[i++] = ch;
        int r = read(sockfd, &ch, 1);
        if (r <= 0) {
            break;
        }
    }
    // 包头(1)	包长度(4)	命令号(4)	回复长度(4)   结果(1)	 回复内容(文件的长度) 包尾(1)
    int pkg_len = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
    if (i != pkg_len) {
#ifdef DEBUG
        printf("i = %d, pkg_len = %d\n", i, pkg_len);
#endif
        return;
    }
    int cmd_no = buf[4] | (buf[5] << 8) | (buf[6] << 16) | (buf[7] << 24);
    if (buf[12]) {
        int errnum = buf[13] | (buf[14] << 8) | (buf[15] << 16) | (buf[16] << 24);
        perror(strerror(errnum));
    } else {
        int filesize = buf[13] | (buf[14] << 8) | (buf[15] << 16) | (buf[16] << 24);
        /*接收数据*/
#ifdef DEBUG
        printf("file size:%d\n", filesize);
#endif
        int cur_read = 0;
        int fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, 0664);
        if (-1 == fd) {
            perror("open failed");
            return;
        }
        if (filesize < 1024) {
            unsigned char rd[1024] = {0};
            int r = read(sockfd, rd, filesize);
            write(fd, rd, r);
            close(fd);
            return;
        }
        while (cur_read < filesize) {
            unsigned char rd[1024] = {0};
            /*如果剩余内容小于1024，直接读完剩余字节*/
            if (filesize - cur_read < 1024) {
                int r = read(sockfd, rd, filesize - cur_read);
                write(fd, rd, r);
                cur_read += r;
                break;
            }
            int r = read(sockfd, rd, sizeof(rd));
            if (r <= 0) {
                break;
            }
            printf("%.0f%%\r", (cur_read * 1.0 / filesize) * 100);
            fflush(stdout);
            write(fd, rd, r);
            cur_read += r;
        }
        printf("\n");
        close(fd);
    }
}

void cmd_put(int sockfd, const char *str) {
    unsigned char file[256] = {0};
    strcpy(file, str);
    char *t = file;
    while (*t == ' ') {
        t++;
    }
    if (strlen(t) == 0 || *t == '\n') {
        fputs("Usage: get filename\n", stderr);
        return;
    }
    char filename[256] = {0};
    int filesize = 0;
    // strncpy(filename, t, strlen(t));
    // filename[strlen(filename) - 1] = '\0';
    sscanf(t, "%s", filename);
    struct stat st;
    if (stat(filename, &st) == -1) {
        perror("put failed");
        return;
    } else if (S_ISREG(st.st_mode)) {
        filesize = st.st_size;
    } else {
        printf("%s is not regular file!\n", filename);
        return;
    }
#ifdef DEBUG
    printf("filesize = %d\n", filesize);
#endif
    int fd = open(filename, O_RDONLY, 0664);
    if (-1 == fd) {
        perror("open failed");
        return;
    }
    unsigned char cmd[1024] = {0};
    int i = 0;
    // 包头(1)	包长度(4)	 命令号(4)  参数长度(4)  参数内容(文件名长度) 参数二内容(4):文件的大小 包尾(1)
    cmd[i++] = 0xc0;
    int arg_len = strlen(filename);
    int pkg_len = 4 + 4 + 4 + arg_len + 4;
    cmd[i++] = 0xff & (pkg_len);
    cmd[i++] = 0xff & (pkg_len >> 8);
    cmd[i++] = 0xff & (pkg_len >> 16);
    cmd[i++] = 0xff & (pkg_len >> 24);
    enum CMD_NO cmd_no = FTP_CMD_PUT;
    cmd[i++] = 0xff & (cmd_no);
    cmd[i++] = 0xff & (cmd_no >> 8);
    cmd[i++] = 0xff & (cmd_no >> 16);
    cmd[i++] = 0xff & (cmd_no >> 24);

    cmd[i++] = 0xff & (arg_len);
    cmd[i++] = 0xff & (arg_len >> 8);
    cmd[i++] = 0xff & (arg_len >> 16);
    cmd[i++] = 0xff & (arg_len >> 24);

    memcpy(cmd + i, filename, arg_len);
    i += arg_len;

    cmd[i++] = 0xff & (filesize);
    cmd[i++] = 0xff & (filesize >> 8);
    cmd[i++] = 0xff & (filesize >> 16);
    cmd[i++] = 0xff & (filesize >> 24);

    cmd[i++] = 0xc0;
    write(sockfd, cmd, i);
    /*开始传送文件上传到服务器*/
    int cur_read = 0;
    while (1) {
        unsigned char buf[1024] = {0};
        int r = read(fd, buf, sizeof(buf));
        if (r <= 0) {
            break;
        }
        if (r < 1024) {
            write(sockfd, buf, r);
            break;
        }
        cur_read += r;
        printf("%.0f%%\r", (cur_read * 1.0 / filesize) * 100);
        fflush(stdout);
        write(sockfd, buf, r);
    }
    printf("\n");
    close(fd);
    /*发送完之后接收服务器的回复信息，判断是否上传成功*/
    recv_put_resp(sockfd, filename);
}

void recv_put_resp(int sockfd, const char *filename) {
    unsigned char resp[1024] = {0};
    int i = 0;
    unsigned char ch;
    do {
        int r = read(sockfd, &ch, 1);
        if (r <= 0) {
            break;
        }
    } while (ch != 0xc0);
    while (ch == 0xc0) {
        int r = read(sockfd, &ch, 1);
        if (r <= 0) {
            break;
        }
    }
    while (ch != 0xc0) {
        resp[i++] = ch;
        if (i >= 1024) {
            printf("the array is too small\n");
            return;
        }
        int r = read(sockfd, &ch, 1);
        if (r <= 0) {
            break;
        }
    }
    // 包头(1)	包长度(4)	命令号(4)	回复长度(4)   结果(1)	 回复内容(文件的长度) 包尾(1)
    int pkg_len = resp[0] | (resp[1] << 8) | (resp[2] << 16) | (resp[3] << 24);
    if (i != pkg_len) {
#ifdef DEBUG
        printf("i = %d, pkg_len = %d\n", i, pkg_len);
#endif
        return;
    }
    int cmd_no = resp[4] | (resp[5] << 8) | (resp[6] << 16) | (resp[7] << 24);
    if (resp[12]) {
        int errnum = resp[13] | (resp[14] << 8) | (resp[15] << 16) | (resp[16] << 24);
        perror(strerror(errnum));
    } else {
        int filesize = resp[13] | (resp[14] << 8) | (resp[15] << 16) | (resp[16] << 24);
        /*接收数据*/
#ifdef DEBUG
        printf("file size:%d\n", filesize);
#endif
        printf("send %s successfully\n", filename);
    }
}

void cmd_pwd(int sockfd) {
    /*准备数据包*/
    unsigned char cmd[1024] = {0};
    int i = 0;
    cmd[i++] = 0xc0;
    int pkg_len = 4 + 4;
    cmd[i++] = 0xff & (pkg_len);
    cmd[i++] = 0xff & (pkg_len >> 8);
    cmd[i++] = 0xff & (pkg_len >> 16);
    cmd[i++] = 0xff & (pkg_len >> 24);
    enum CMD_NO cmd_no = FTP_CMD_PWD;
    cmd[i++] = 0xff & (cmd_no);
    cmd[i++] = 0xff & (cmd_no >> 8);
    cmd[i++] = 0xff & (cmd_no >> 16);
    cmd[i++] = 0xff & (cmd_no >> 24);
    cmd[i++] = 0xc0;
    write(sockfd, cmd, i);
}

void recv_pwd_resp(int sockfd) {
    unsigned char ch;
    unsigned char buf[1024] = {0};
    int i = 0;
    do {
        int r = read(sockfd, &ch, 1);
        if (r <= 0) {
            break;
        }
    } while (ch != 0xc0);
    while (ch == 0xc0) {
        int r = read(sockfd, &ch, 1);
        if (r <= 0) {
            break;
        }
    }
    while (ch != 0xc0) {
        buf[i++] = ch;
        int r = read(sockfd, &ch, 1);
            if (r <= 0) {
                break;
            }
    }
    int pkg_len = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
    if (i != pkg_len) {
        return;
    }
    int resp_len = buf[8] | (buf[9] << 8) | (buf[10] << 16) | (buf[11] << 24);
    if (buf[12]) {
        int errnum = buf[13] | (buf[14] << 8) | (buf[15] << 16) | (buf[16] << 24);
        perror(strerror(errnum));
    } else {
        char curr_dir[256] = {0};
        memcpy(curr_dir, buf + 13, resp_len - 1);
        printf("pwd: %s\n", curr_dir);
    }
}

void cmd_cd(int sockfd, const char *dirname_) {
    char str[256] = {0};
    strcpy(str, dirname_);
    char *t = str;
    while (*t == ' ') {
        t++;
    }
    if (*t == '\n') {
        printf("Usage cd dirname\n");
        return;
    }
    char dirname[256] = {0};
    sscanf(t, "%s", dirname);
    unsigned char cmd[1024] = {0};
    int i = 0;
    int arg_len = strlen(dirname);
    int pkg_len = 4 + 4 + 4 + arg_len;
    cmd[i++] = 0xc0;
    cmd[i++] = 0xff & (pkg_len);
    cmd[i++] = 0xff & (pkg_len >> 8);
    cmd[i++] = 0xff & (pkg_len >> 8);
    cmd[i++] = 0xff & (pkg_len >> 8);
    enum CMD_NO cmd_no = FTP_CMD_CD;
    cmd[i++] = 0xff & (cmd_no);
    cmd[i++] = 0xff & (cmd_no >> 8);
    cmd[i++] = 0xff & (cmd_no >> 8);
    cmd[i++] = 0xff & (cmd_no >> 8);
    cmd[i++] = 0xff & (arg_len);
    cmd[i++] = 0xff & (arg_len >> 8);
    cmd[i++] = 0xff & (arg_len >> 8);
    cmd[i++] = 0xff & (arg_len >> 8);
    memcpy(cmd + i, dirname, arg_len);
    i += arg_len;
    cmd[i++] = 0xc0;
    write(sockfd, cmd, i);
}

void recv_cd_resp(int sockfd) {
    unsigned char ch;
    unsigned char buf[1024] = {0};
    int i = 0;
    do {
        int r = read(sockfd, &ch, 1);
        if (r <= 0) {
            break;
        }
    } while (ch != 0xc0);
    while (ch == 0xc0) {
        int r = read(sockfd, &ch, 1);
        if (r <= 0) {
            break;
        }
    }
    while (ch != 0xc0) {
        buf[i++] = ch;
        int r = read(sockfd, &ch, 1);
            if (r <= 0) {
                break;
            }
    }
    int pkg_len = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
    if (i != pkg_len) {
        return;
    }
    int resp_len = buf[8] | (buf[9] << 8) | (buf[10] << 16) | (buf[11] << 24);
    if (buf[12]) {
        int errnum = buf[13] | (buf[14] << 8) | (buf[15] << 16) | (buf[16] << 24);
        perror(strerror(errnum));
    } else {
        char curr_dir[256] = {0};
        memcpy(curr_dir, buf + 13, resp_len - 1);
        printf("cd: %s\n", curr_dir);
    }
}

void cmd_getdir(int sockfd, char *dirname_) {
    char str[256] = {0};
    strcpy(str, dirname_);
    char *t = str;
    while (*t == ' ') {
        t++;
    }
    if (*t == '\n') {
        printf("Usage getdir dirname\n");
        return;
    }
    char dirname[256] = {0};
    sscanf(t, "%s", dirname);
    unsigned char cmd[1024] = {0};
    int i = 0;
    int arg_len = strlen(dirname);
    int pkg_len = 4 + 4 + 4 + arg_len;
    cmd[i++] = 0xc0;
    cmd[i++] = 0xff & (pkg_len);
    cmd[i++] = 0xff & (pkg_len >> 8);
    cmd[i++] = 0xff & (pkg_len >> 8);
    cmd[i++] = 0xff & (pkg_len >> 8);
    enum CMD_NO cmd_no = FTP_CMD_GETDIR;
    cmd[i++] = 0xff & (cmd_no);
    cmd[i++] = 0xff & (cmd_no >> 8);
    cmd[i++] = 0xff & (cmd_no >> 8);
    cmd[i++] = 0xff & (cmd_no >> 8);
    cmd[i++] = 0xff & (arg_len);
    cmd[i++] = 0xff & (arg_len >> 8);
    cmd[i++] = 0xff & (arg_len >> 8);
    cmd[i++] = 0xff & (arg_len >> 8);
    memcpy(cmd + i, dirname, arg_len);
    i += arg_len;
    cmd[i++] = 0xc0;
    write(sockfd, cmd, i);
    recv_getdir_resp(sockfd, dirname);
}

void recv_getdir_resp(int sockfd, const char *dirname) {
    unsigned char buf[1024] = {0};
    int i = 0;
    unsigned char ch;
    do {
        int r = read(sockfd, &ch, 1);
        if (r <= 0) {
            break;
        }
    } while(ch != 0xc0);
    while (ch == 0xc0) {
        int r = read(sockfd, &ch, 1);
        if (r <= 0) {
            break;
        }
    } 
    while (ch != 0xc0) {
        buf[i++] = ch;
        int r = read(sockfd, &ch, 1);
        if (r <= 0) {
            break;
        }
    }
    // 包头(1) 	包长度(4) 	命令号(4) 	回复长度(4)	   结果(1)  回复内容(文件夹的大小/错误码) 包尾(1)
    int pkg_len = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
    if (i != pkg_len) {
#ifdef DEBUG
        printf("pkg_len = %d, i = %d\n", pkg_len, i);
        return;
#endif
    }
    int cmd_no = buf[4] | (buf[5] << 8) | (buf[6] << 16) | (buf[7] << 24);
    int resp_len = buf[8] | (buf[9] << 8) | (buf[10] << 16) | (buf[11] << 24);
    if (buf[12]) {
        int errnum = buf[13] | (buf[14] << 8) | (buf[15] << 16) | (buf[16] << 24);
        perror(strerror(errnum));
        return;
    } else {
        /*如果正常运行，创建文件夹*/
        mkdir(dirname, 0777);
        char curr_dir[256] = {0};
        getcwd(curr_dir, sizeof(curr_dir));
        chdir(dirname);
        char dir_name[256] = {0};
        getcwd(dir_name, sizeof(dir_name));
        /*如果收到结束标志*/
        /*接收下一个数据包*/
        char filename[256] = {0};
        char type;
        read(sockfd, &type, 1);
        read(sockfd, filename, sizeof(filename));
        while (strncmp(filename, "over", 4)) {
            if (type == 'd') {
#ifdef DEBUG
                printf("type = dir\n");
#endif
                recv_getdir_resp(sockfd, filename);
                chdir(dir_name);
            } else if (type == 'r') {
#ifdef DEBUG
                printf("type = reg\n");
#endif
                recv_get_resp(sockfd, filename);
            }
            read(sockfd, &type, 1);
            read(sockfd, filename, sizeof(filename));
        }
        chdir(curr_dir);
    }
}

void cmd_putdir(int sockfd, const char *filename_) {
    char str[256] = {0};
    strcpy(str, filename_);
    char *t = str;
    while (*t == ' ') {
        t++;
    }
    if (*t == '\n') {
        printf("Usage _putdir dirname\n");
        return;
    }
    char dirname[256] = {0};
    sscanf(t, "%s", dirname);
    unsigned char cmd[1024] = {0};
    int i = 0;
    int arg_len = strlen(dirname);
    DIR *dirp = opendir(dirname);
    if (dirp == NULL) {
        perror("opendir failed");
        return;
    }
    int pkg_len = 4 + 4 + 4 + arg_len;
    cmd[i++] = 0xc0;
    cmd[i++] = 0xff & (pkg_len);
    cmd[i++] = 0xff & (pkg_len >> 8);
    cmd[i++] = 0xff & (pkg_len >> 8);
    cmd[i++] = 0xff & (pkg_len >> 8);
    enum CMD_NO cmd_no = FTP_CMD_PUTDIR;
    cmd[i++] = 0xff & (cmd_no);
    cmd[i++] = 0xff & (cmd_no >> 8);
    cmd[i++] = 0xff & (cmd_no >> 8);
    cmd[i++] = 0xff & (cmd_no >> 8);
    cmd[i++] = 0xff & (arg_len);
    cmd[i++] = 0xff & (arg_len >> 8);
    cmd[i++] = 0xff & (arg_len >> 8);
    cmd[i++] = 0xff & (arg_len >> 8);
    memcpy(cmd + i, dirname, arg_len);
    i += arg_len;
    cmd[i++] = 0xc0;
    write(sockfd, cmd, i);
    /*如果运行正常，开始上传文件*/
    struct dirent *dp = NULL;
    char dir_name[256] = {0};
    char curr_dir[256] = {0};
    getcwd(curr_dir, sizeof(curr_dir));
    chdir(dirname);
    getcwd(dir_name, sizeof(dir_name));
    while (dp = readdir(dirp)) {
        if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0) {
            continue;
        }
        /*先发送文件名和类型和大小*/
        /*再发送文件内容*/
        if (dp->d_type == DT_DIR) {
#ifdef DEBUG
            printf("send dir %s/%s\n", dir_name, dp->d_name);
#endif
            struct stat st;
            stat(dp->d_name, &st);
            int filesize = st.st_size;
            write(sockfd, "d", 1);
            write(sockfd, dp->d_name, 256);
            unsigned char fs[4] = {0};
            fs[0] = 0xff & filesize;
            fs[1] = 0xff & (filesize >> 8);
            fs[2] = 0xff & (filesize >> 16);
            fs[3] = 0xff & (filesize >> 24);
            write(sockfd, fs, sizeof(fs));
            cmd_putdir(sockfd, dp->d_name);         
            chdir(dir_name);
        } else if (dp->d_type == DT_REG) {
#ifdef DEBUG
            printf("send file %s/%s\n", dir_name, dp->d_name);
#endif
            struct stat st;
            stat(dp->d_name, &st);
            int filesize = st.st_size;
            write(sockfd, "r", 1);
            write(sockfd, dp->d_name, 256);
            unsigned char fs[4] = {0};
            fs[0] = 0xff & filesize;
            fs[1] = 0xff & (filesize >> 8);
            fs[2] = 0xff & (filesize >> 16);
            fs[3] = 0xff & (filesize >> 24);
            write(sockfd, fs, sizeof(fs));
            cmd_put(sockfd, dp->d_name);
        }
    }
    /*如果循环结束，就发送结束标志*/
#ifdef DEBUG
    printf("发送结束标志\n");
#endif
    write(sockfd, "#", 1);
    write(sockfd, "over", 256);
    write(sockfd, "1234", 4);
}

void manual() {
    printf("command [options]\n");
    printf("cd remote-directory\n\
                -Change the working directory on the remote machine to remote-directory.\n");
    printf("clear \n\
                -clear current screen\n");
    printf("ls \n\
                -list current directory items\n");
    printf("get remote-file [local-file]\n\
                -get remote file from server to local\n");
    printf("put local-file [remote-file]\n\
                -put local file to remote server from local\n");
    printf("_getdir remote-directory [local-directory]\n\
                -get remote directory from remote server to local\n");
    printf("_putdir remote-directory [local-directory]\n\
                -put local directory to remote server\n");
    printf("pwd\n\
                -Print the name of the current working directory on the remote machine.\n");
    printf("quit\n\
                -A synonym for bye.\n");
}

void cmd_stat(int sockfd, const char *str) {
    char file[256] = {0};
    strcpy(file, str);
    char *t = file;
    /*获取文件名，跳过空格*/
    while (*t == ' ') {
        t++;
    }
    if (strlen(t) == 0 || *t == '\n') {
        fputs("Usage: stat filename\n", stderr);
        return;
    }
    char filename[256] = {0};
    // strncpy(filename, t, strlen(t));
    sscanf(t, "%s", filename);
    unsigned char cmd[1024] = {0};
    int i = 0;
    cmd[i++] = 0xc0;
    int arg_len = strlen(filename);
    int pkg_len = 4 + 4 + 4 + arg_len;
    enum CMD_NO cmd_no = FTP_CMD_STAT;
    cmd[i++] = 0xff & (pkg_len);
    cmd[i++] = 0xff & (pkg_len >> 8);
    cmd[i++] = 0xff & (pkg_len >> 8);
    cmd[i++] = 0xff & (pkg_len >> 8);
    cmd[i++] = 0xff & (cmd_no);
    cmd[i++] = 0xff & (cmd_no >> 8);
    cmd[i++] = 0xff & (cmd_no >> 8);
    cmd[i++] = 0xff & (cmd_no >> 8);
    cmd[i++] = 0xff & (arg_len);
    cmd[i++] = 0xff & (arg_len >> 8);
    cmd[i++] = 0xff & (arg_len >> 8);
    cmd[i++] = 0xff & (arg_len >> 8);
    memcpy(cmd + i, filename, arg_len);
    i += arg_len;
    cmd[i++] = 0xc0;
    write(sockfd, cmd, i);
}

void recv_stat_resp(int sockfd) {
    unsigned char resp[1024] = {0};
    int i = 0;
    unsigned char ch;
    do {
        int r = read(sockfd, &ch, 1);
        if (r <= 0) {
            break;
        }
    } while (ch != 0xc0);
    while (ch == 0xc0) {
        int r = read(sockfd, &ch, 1);
        if (r <= 0) {
            break;
        }
    }
    while (ch != 0xc0) {
        resp[i++] = ch;
        int r = read(sockfd, &ch, 1);
        if (r <= 0) {
            break;
        }
    }
    int pkg_len = resp[0] | (resp[1] << 8) | (resp[2] << 16) | (resp[3] << 24);
    if (pkg_len != i) {
        return;
    }
    if (resp[8]) {
        return;
    }
    unsigned char type = resp[9];
    if (type == 'r') {
        printf("regular\n");
    } else if (type == 'd') {
        printf("directory\n");
    }
}
